package cn.rjzjh.tapestry.component.components.base;

import org.apache.tapestry5.BindingConstants;
import org.apache.tapestry5.ClientElement;
import org.apache.tapestry5.ComponentResources;
import org.apache.tapestry5.MarkupWriter;
import org.apache.tapestry5.SymbolConstants;
import org.apache.tapestry5.annotations.AfterRender;
import org.apache.tapestry5.annotations.BeginRender;
import org.apache.tapestry5.annotations.Environmental;
import org.apache.tapestry5.annotations.Parameter;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.ioc.annotations.Symbol;
import org.apache.tapestry5.json.JSONObject;
import org.apache.tapestry5.services.Environment;
import org.apache.tapestry5.services.javascript.JavaScriptSupport;

/*****
 * 组件的公共父类，如果是html的元素不要在组件中定义，所有组件都会把非正式的参数原样输出到客户端
 * 
 * @author 周俊辉
 * 
 */
public abstract class AbstractExtendableComponent implements ClientElement {
	/**
	 * 公共参数：客户端Id，jquery据此字段查到此组件。<br/>
	 * 类型：字符串
	 * 
	 */
	@Parameter(defaultPrefix = BindingConstants.LITERAL)
	private String id;
	/****
	 * 公共参数：初始化方法。<br/>
	 * 类型：整型
	 */
	@Parameter(defaultPrefix = BindingConstants.LITERAL)
	private String initMethod;

	@Environmental
	protected JavaScriptSupport javaScriptSupport;

	@Inject
	protected Environment environment;
	
	@Inject
	@Symbol(SymbolConstants.CONTEXT_PATH) 
	protected String contextPath;

	/****
	 * 组件绑定的值，可以是变量，也可以是常量，常量要加前缀literal：,例如： literal:2014-08-09
	 */
	@Parameter(required = false, principal = true, autoconnect = true)
	protected Object value;

	/****
	 * 公共参数：其它未封装的参数可通过它进行配置。<br/>
	 * 类型：json对象
	 */
	@Parameter(required = false, defaultPrefix = BindingConstants.LITERAL)
	private JSONObject params;// 其它附加参数

	private String defaultInitMethod;

	@Inject
	private JavaScriptSupport support;

	protected boolean needInformalParam = true;// 是否需要rend非正式参数
	


	@Inject
	protected ComponentResources resources;

	protected final void setDefaultMethod(String methodName) {
		this.defaultInitMethod = methodName;
	}

	@AfterRender
	protected void addJSResources() {
	}

	@AfterRender
	protected void addCSSResources() {
	}

	public void setInitMethod(String initMethod) {
		this.initMethod = initMethod;
	}

	public String getInitMethod() {
		return (initMethod == null) ? defaultInitMethod : initMethod;
	}

	public String getId() {
		if (id == null) {
			id = support.allocateClientId(resources);
		}
		return this.id;
	}

	@BeginRender
	void begin(MarkupWriter writer) {
		JSONObject spec=new JSONObject();
		spec.put("id", getClientId());
		if (!resources.isBound("params")) {
			params = new JSONObject();
		}
		spec.put("params", params);
		writeFieldTag(writer, spec);
		if (needInformalParam) {
			resources.renderInformalParameters(writer);
		}
	}

	protected abstract void writeFieldTag(MarkupWriter writer,
			final JSONObject spec);

	@Override
	public String getClientId() {
		return getId();
	}
}
